﻿using System;
using System.IO.Ports;
using System.Threading;

namespace SerialPort_Assistant
{
     partial class Form1 { 
    
        const double MAX_WIDTH = 3.0;
        const int HALF_GRID_SIZE = 6;
        public  int Action_Space_N = 8;
        public  int Observation_Space_N = (2*HALF_GRID_SIZE)*(2*HALF_GRID_SIZE);

        private (int,int) observation;



        public double vol1,vol2,vol3,vol4;
        double volStep = 10;
        private double reward;
        private bool done;
        private Random random = new Random();


        public ((int,int), double, bool) Step(int action)
        {
            int old_dist = get_observation();
            switch(action)
            { 
                 case 0:
                    vol1 += volStep;
                    doAction(vol1,0,0,0);
                    break;
                 case 1:
                     vol2 += volStep;
                      doAction(0,vol2,0,0);
                    break;
                 case 2:
                    vol3+= volStep;
                    doAction(0,0,vol3,0);
                    break;
                 case 3:
                     vol4+= volStep;
                     doAction(0,0,0,vol4);
                    break;
                 case 4:
                    vol1 -= volStep;
                    doAction(vol1,0,0,0);
                    break;
                 case 5:
                     vol2 -= volStep;
                      doAction(0,vol2,0,0);
                    break;
                 case 6:
                    vol3 -= volStep;
                    doAction(0,0,vol3,0);
                    break;
                 case 7:
                     vol4 -= volStep;
                     doAction(0,0,0,vol4);
                    break;
            }
           int new_dist = get_observation();
           reward = new_dist<old_dist ? 1:-1;
            done = false;
            if( new_dist <= 2)
            { 
                done = true;
            }
           return (observation, reward, done);
        }

        public (int,int) Reset()
        {
            doAction(0,0,0,0);
            done = false;
            vol1=vol2=vol3=vol4 = 0;
            get_observation();

            return observation;
        }

        public int Random_Action()
        {
            return random.Next(0, Action_Space_N);
        }
        private int get_observation()
        {
            last_Near_Row = cur_Near_Row;
            last_Near_Col = cur_Near_Col;
            last_Far_Row = cur_Far_Row;
            last_Far_Col = cur_Far_Col;

            cur_Near_Row = psd_A_x1;
            cur_Near_Col = psd_A_y1;
            cur_Far_Row = psd_B_x2;
            cur_Far_Col = psd_B_y2;

            int sign = cur_Near_Row>0 ? 1 : -1;
            int row_cnt = (int)Math.Ceiling(( Math.Abs(cur_Near_Row) / MAX_WIDTH) * HALF_GRID_SIZE) *sign;
            sign = cur_Near_Col>0 ? 1 : -1;
            int col_cnt = (int)Math.Ceiling(( Math.Abs(cur_Near_Col) / MAX_WIDTH) * HALF_GRID_SIZE) * sign;
            observation = (row_cnt , col_cnt);
            int dist = Math.Abs(observation.Item1) + Math.Abs(observation.Item2);
            return dist;

        }

        public int GetStateIdx((int,int) state)
        { 
            int row = (state.Item1 - (-6)) ;
            int col = (state.Item2 - (-6)) ;
           int idx = row * (2*HALF_GRID_SIZE) + col;
            return idx;
         }
       
       
    }
}